package com.liu.designmode.proxy.binding;

import com.liu.designmode.proxy.annotations.Params;
import com.liu.designmode.proxy.annotations.Select;
import com.liu.designmode.proxy.bean.Employee;
import com.liu.designmode.proxy.type.TypeHandlerFactory;
import com.liu.designmode.proxy.utils.GenericTokenParser;
import com.liu.designmode.proxy.utils.ParameterMappingTokenHandler;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 这个类应该是mybatis增强的源码
 */
public class MapperProxy implements InvocationHandler {

    // 需要明确代理谁，目标类应该如何和当前代理类关联起来
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 1.获取连接
        Connection connection = getConnection();
        // 2.获取方法上的注解信息
        Select selectAnnotation = method.getAnnotation(Select.class);
        String text = selectAnnotation.value();
        // 3.#{xx} -> ?
        ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
        GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler);
        String sql = genericTokenParser.parse(text);
        PreparedStatement ps = connection.prepareStatement(sql);
        // 4. 设置方法参数
        List<String> parameterList = parameterMappingTokenHandler.getParameterMappings();
        Map<String, Object> paramValueMap = new HashMap<>();
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            Params annotation = parameter.getAnnotation(Params.class);
            String value = annotation.value();
            paramValueMap.put(value, args[i]);
        }
        for (int i = 0; i < parameterList.size(); i++) {
            String jdbcColumnName = parameterList.get(i);
            Object val = paramValueMap.get(jdbcColumnName);
            TypeHandlerFactory.get(val.getClass()).setParameter(ps, i+1, val);
        }
        // 5.获取结果
        ps.execute();
        ResultSet resultSet = ps.getResultSet();
        List<Employee> result = new ArrayList<>();
        while (resultSet.next()) {
            result.add(new Employee(resultSet.getString("name"),
                    resultSet.getInt("age"),
                    resultSet.getString("email"),
                    resultSet.getInt("sex")));
        }
        // 6.释放资源
        resultSet.close();
        ps.close();
        return result;
    }




    // MySQL 连接信息
    private static final String URL = "jdbc:mysql://localhost:3306/seckill?serverTimezone=UTC&useSSL=false";
    private static final String USER = "root";
    private static final String PASSWORD = "s123456s";

    public Connection getConnection() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
            return conn;
        } catch (Exception e) {
            System.err.println("驱动加载失败：" + e.getMessage());
            return null;
        }
    }
}
